'use strict';

var utils = require('./utils');
var bind = require('./helpers/bind');
var Axios = require('./core/Axios');
var mergeConfig = require('./core/mergeConfig');
var defaults = require('./defaults');

/**
 * Create an instance of Axios
 *
 * @param {Object} defaultConfig The default config for the instance
 * @return {Axios} A new instance of Axios
 */
function createInstance(defaultConfig) {
    // 实例化Axios
    var context = new Axios(defaultConfig);
    // 注意这里bind是一个自定义函数，返回一个函数（）=>{Axios.prototype.request.apply(context,args)}
    // 这里request基本是Axios的核心方法，相当于将这些方法全部绑到了实例化的对象上
    // 后续每次调用axios其实是调用Axios.prototype.request方法
    var instance = bind(Axios.prototype.request, context);

    // Copy axios.prototype to instance
    // 将Axios原型链上的其他方法也都绑定到instance上去，这些方法的this会指向contxt
    // 所以axios具有Axios.prototype的方法和属性
    utils.extend(instance, Axios.prototype, context);

    // Copy context to instance
    // 将contxt上的属性复制到instance上去
    utils.extend(instance, context);

    return instance;
}

// Create the default instance to be exported
var axios = createInstance(defaults);

// Expose Axios class to allow class inheritance
// 暴露 Axios 类， 允许类继承
axios.Axios = Axios;

// Factory for creating new instances
// 创建实例的工厂函数
axios.create = function create(instanceConfig) {
    return createInstance(mergeConfig(axios.defaults, instanceConfig));
};

// Expose Cancel & CancelToken
axios.Cancel = require('./cancel/Cancel');
axios.CancelToken = require('./cancel/CancelToken');
axios.isCancel = require('./cancel/isCancel');

// Expose all/spread
// 处理并发请求，直接调用了Priomise的all方法
// axios.all方法接受一个数组作为参数，数组中的每个元素都是一个请求，返回一个promise对象，
// 当数组中所有请求均已完成时，执行then方法。
axios.all = function all(promises) {
    return Promise.all(promises);
};
// 在then方法中执行axios.spread 方法。该方法是接收一个函数作为参数，
// 返回一个新的函数。接收的参数函数的参数是axios.all方法中每个请求返回的响应。
axios.spread = require('./helpers/spread');

// Expose isAxiosError
// 判断是否是axios导致的错误
axios.isAxiosError = require('./helpers/isAxiosError');
// 暴露出axios
module.exports = axios;

// Allow use of default import syntax in TypeScript
module.exports.default = axios;